Autor: Leonardo Simões
Este é um projeto guiado da Digital Innovation One: "Criando modelos com Python e Machine Learning para prever a evolução do COVID-19 no Brasil". O objetivo é analisar os dados das séries temporais e usar algum modelo ARIMA para predição.
Os dados usados foram obtidos na plataforma do Kaggle: https://www.kaggle.com/datasets/sudalairajkumar/novel-corona-virus-2019-dataset
Na etapa de preparação dos dados são realizadas algumas operações que precedem a análise dos dados:
# Imports das bibliotecas mais usadas
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
# Imports da biblioteca Plotly
import plotly
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# Imports das bibliotecas para séries temporais
from datetime import datetime
from statsmodels.tsa.seasonal import seasonal_decompose
from statsmodels.tsa.stattools import adfuller
from pmdarima.arima import auto_arima
import joblib
# Definições de formatação de números decimais
pd.options.display.float_format = '{:20,.2f}'.format
np.set_printoptions(precision=2)
# Definição da função load_df_temporal_series()
def load_df_temporal_series(diretorio_do_arquivo):
"""
Carrega os dados em um dataframe.
Renomeia as colunas do dataframe.
Remove linhas duplicadas no dataframe.
Ordena os valores por 'Data'.
Retorna um DataFrame
Argumento:
diretorio_do_arquivo -- o diretório do arquivo arquivo de csv.
"""
dateparse = lambda x: datetime.strptime(x, '%m/%d/%Y')
colunas_usadas = ['ObservationDate', 'Country/Region', 'Confirmed','Deaths','Recovered']
df = pd.read_csv(diretorio_do_arquivo, usecols=colunas_usadas, parse_dates=['ObservationDate'], date_parser=dateparse)
colunas_renomeadas = {'ObservationDate':'Data', 'Country/Region':'Pais', 'Confirmed':'Casos',
'Deaths':'Mortes', 'Recovered':'Recuperados'}
df.rename(columns=colunas_renomeadas, inplace=True)
df.drop_duplicates(keep='first', inplace=True)
df.sort_values(by=['Data'], inplace=True)
return df
# Definição da função somar_agrupamento()
def somar_agrupamento(df, colunas_agrupamento, colunas_soma):
"""
Retorna um dataframe de soma por grupo.
Argumentos:
df -- DataFrame
colunas_agrupamento -- list
colunas_soma -- list
"""
df_agrupado = df.groupby(colunas_agrupamento, as_index=False)
df_soma = df_agrupado[colunas_soma].sum()
return df_soma
# Definição da função mesclar_colunas()
def mesclar_colunas(df, colunas_id, colunas_valores, nome_variavel = 'Variavel', nome_value = 'Valor'):
"""
Retorna um dataframe mesclado.
Argumentos:
df -- DataFrame
colunas_id -- list
colunas_valores -- list
nome_variavel -- string (Opcional - Valor padrão é 'Variavel')
nome_value -- string (Opcional - Valor padrão é 'Valor')
"""
df_m = pd.melt(df, id_vars=colunas_id, value_vars=colunas_valores)
df_m.rename(columns={'variable':nome_variavel, 'value':nome_value}, inplace=True)
return df_m
# Definição da função plotar_linha()
def plotar_linha(df, eixo_x, eixo_y='Quantidade', titulo='Titulo', categorias=None):
"""
Plota um gráfico de linhas.
Argumentos:
df -- DataFrame
eixo_x -- string
eixo_y -- string (Opcional - Valor padrão é 'Quantidade')
titulo -- string (Opcional - Valor padrão é 'Titulo')
categorias -- string (Opcional - Valor padrão é None)
"""
fig = px.line(df, x=eixo_x, y=eixo_y,
color=categorias
)
fig.update_layout(title_text=titulo, title_x=0.5,
legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01)
)
fig.show()
# Definição da função plotar_componentes_serie()
def plotar_componentes_serie(serie):
"""
Plota gráficos da série e de suas componentes.
Argumentos:
serie -- Serie
"""
decomposicao = seasonal_decompose(serie)
fig = decomposicao.plot();
fig.set_size_inches((11, 6));
fig.tight_layout();
plt.show();
# Definição da função diferenciar_serie()
def diferenciar_serie(serie):
"""
Retorna uma série diferenciada em um passo.
Argumentos:
serie -- Serie
"""
return serie.diff().dropna()
# Definição da função salvar_modelo_arquivo()
def salvar_modelo_arquivo(modelo, nome_arquivo='ModeloARIMA'):
"""
Salvar um modelo em um arquivo .pkl
Argumentos:
modelo -- model ARIMA
nome_arquivo -- string (Opcional - Valor padrão é 'ModeloARIMA')
"""
nome_arquivo = nome_arquivo + '.pkl'
joblib.dump(modelo, nome_arquivo)
# Diretório do arquivo de dados
ARQUIVO = './data/covid_19_data.csv'
df = load_df_temporal_series(ARQUIVO)
df.head()
df_soma_mundo = somar_agrupamento(df, colunas_agrupamento=['Data'], colunas_soma=['Casos','Mortes','Recuperados'])
df_soma_mundo.head()
df_brasil = df.loc[(df['Pais'] == 'Brazil') & (df['Data'] >= '2020-02-26')]
df_brasil.head()
df_soma_brasil = somar_agrupamento(df_brasil, colunas_agrupamento=['Data'], colunas_soma=['Casos','Mortes','Recuperados'])
df_soma_brasil.tail()
df_melt_br = mesclar_colunas(df_soma_brasil, colunas_id=['Data'], colunas_valores=['Casos', 'Mortes', 'Recuperados'], nome_variavel='Tipo', nome_value='Quantidade')
df_melt_br.head()
df_melt_mundo = mesclar_colunas(df_soma_mundo, colunas_id=['Data'], colunas_valores=['Casos', 'Mortes', 'Recuperados'], nome_variavel='Tipo', nome_value='Quantidade')
df_melt_mundo.head()
casos_br = df_soma_brasil.set_index('Data')['Casos']
novos_casos_br = diferenciar_serie(casos_br)
novos_casos_br.head()
plotar_linha(df_melt_br, eixo_x='Data', eixo_y='Quantidade', titulo='COVID no Brasil', categorias='Tipo')
plotar_linha(df_melt_mundo, eixo_x='Data', eixo_y='Quantidade', titulo='COVID no Mundo', categorias='Tipo')
# Definindo 'Data' como index
df_soma_brasil.set_index('Data', inplace=True)
df_soma_brasil.head()
df_soma_mundo.describe()
df_soma_brasil.describe()
plotar_componentes_serie(df_soma_brasil['Casos'])
plotar_componentes_serie(df_soma_brasil['Mortes'])
plotar_componentes_serie(df_soma_brasil['Recuperados'])
plotar_componentes_serie(novos_casos_br)
Nesta etapa é treinado um modelo para prever novos casos de Covid no Brasil usandos os dados passados.
modelo = auto_arima(novos_casos_br)
modelo
modelo.summary()
O modelo obtido foi:
$$ARIMA(5,1,2) y_t = \sum_{i=1}^5 a_iy_{t-i} + \sum_{j=1}^2 m_j\epsilon_{t-j} + \epsilon_t$$$$ARIMA(5,1,2) y_t = 0.0505y_{t-1} - 0.5355y_{t-2} - 0.4052y_{t-3} - 0.3912y_{t-4} - 0.4873y_{t-5} -0.9754\epsilon_{t-1} + 0.6754\epsilon_{t-2} + \epsilon_t$$modelo.plot_diagnostics(figsize=(13, 9));
novos_casos_preditos = modelo.predict(n_periods=30)
novos_casos_preditos= novos_casos_preditos.to_frame().reset_index()
novos_casos_preditos.rename(columns={'index': 'Data', 0:'Casos'}, inplace=True)
novos_casos_preditos['Tipo'] = 'Predito'
novos_casos_preditos.tail()
novos_casos_parcela = novos_casos_br[-200:].copy()
#novos_casos_parcela = df_soma_brasil['Casos'][-200:].copy()
novos_casos_br = diferenciar_serie(casos_br)
novos_casos_parcela = novos_casos_parcela.to_frame().reset_index()
#novos_casos_parcela.rename(columns={'index': 'Data', 0:'Casos'}, inplace=True)
novos_casos_parcela['Tipo'] = 'Real'
novos_casos_parcela.tail()
df_novos_casos = pd.concat([novos_casos_parcela, novos_casos_preditos])
titulo_pred = 'Números de novos casos de Covid no Brasil (Real X Predito)'
plotar_linha(df_novos_casos, eixo_x='Data', eixo_y='Casos', titulo=titulo_pred, categorias='Tipo')
salvar_modelo_arquivo(modelo, nome_arquivo='Modelo_ARIMA-Covid-Brasil')
DIO (Digital Innovation One): Criando modelos com Python e Machine Learning para prever a evolução do COVID-19 no Brasil
KAGGLE - Novel Corona Virus 2019 Dataset: https://www.kaggle.com/datasets/sudalairajkumar/novel-corona-virus-2019-dataset
TOWARDS DATA SCIENCE - Time Series forecasting using Auto ARIMA in python: https://towardsdatascience.com/time-series-forecasting-using-auto-arima-in-python-bb83e49210cd